home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / convers.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  26.7 KB  |  1,104 lines

  1. /* convers server - based on conversd written by DK5SG
  2.  * ported to WNOS by DB3FL - 9109xx/9110xx
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <ctype.h>
  9. #ifdef    UNIX
  10. #include <sys/types.h>
  11. #include <sys/stat.h>
  12. #endif
  13. #include <io.h>
  14. #include "global.h"
  15. #include "config.h"
  16. #ifdef CONVERS
  17. #ifdef MAILBOX
  18. #include "mailbox.h"
  19. #include "netuser.h"
  20. #endif
  21. #include "timer.h"
  22. #include "smtp.h"
  23. #include "cmdparse.h"
  24. #include "socket.h"
  25. #include "session.h"
  26. #include "files.h"
  27. #ifdef LZW
  28. #include "lzw.h"
  29. #endif
  30.  
  31. #define LINK        1
  32.  
  33. #ifdef LINK
  34. static struct proc *child = NULLPROC;
  35. static void connect_permlinks __ARGS((int a, void *b, void *c));
  36. #endif
  37.  
  38. static void conv_incom __ARGS((int s, void *t, void *p));
  39. static char * near getarg __ARGS((char *line, int all));
  40.  
  41. static int Sconv = -1;
  42. #ifdef LZW
  43. static int Sxconv = -1;
  44. #endif
  45.  
  46. static char *myhostname = NULLCHAR;
  47. static char cnumber[] = "*** Channel numbers must be in the range 0..%d.\n";
  48.  
  49. #define MAXCHANNEL         32766
  50. #define LINELEN            256
  51. #define CBUFLEN            2048
  52. #define MAX_WAITTIME    (60*60*3)
  53.  
  54. struct convection {
  55.   int  type;                    /* Connection type */
  56. #define CT_UNKNOWN      0
  57. #define CT_USER         1
  58. #define CT_HOST         2
  59. #define CT_CLOSED       3
  60.   char  name[80];                  /* Name of user or host */
  61.   char  host[80];                /* Name of host where user is logged on */
  62.   struct convection *via;       /* Pointer to neighbor host */
  63.   int  channel;                 /* Channel number */
  64.   int32 time;                   /* Connect time */
  65.   int  locked;                  /* Set if mesg already sent */
  66.   int  fd;                        /* Socket descriptor */
  67.   int  fmask;                   /* Socket mask */
  68.   char  *ibuf;                    /* Input buffer */
  69.   int  received;                /* Number of bytes received */
  70.   int  xmitted;                 /* Number of bytes transmitted */
  71.   struct convection *next;      /* Linked list pointer */
  72. };
  73.  
  74. #define CM_UNKNOWN   (1 << CT_UNKNOWN)
  75. #define CM_USER      (1 << CT_USER)
  76. #define CM_HOST      (1 << CT_HOST)
  77. #define CM_CLOSED    (1 << CT_CLOSED)
  78.  
  79. #define NULLCONNECTION  ((struct convection *) 0)
  80.  
  81. static struct convection *convections;
  82.  
  83. struct permlink {
  84.   char name[80];                /* Name of host */
  85.   char link_info[80];              /* Name of socket to connect to */
  86.   char command[80];                 /* Optional connect command */
  87.   struct convection *convection;/* Pointer to associated connection */
  88.   int32 statetime;              /* Time of last (dis)connect */
  89.   int  tries;                   /* Number of connect tries */
  90.   int32 waittime;               /* Time between connect tries */
  91.   int32 retrytime;              /* Time of next connect try */
  92.   int fd;                        /* socket descriptor */
  93.   struct permlink *next;        /* Linked list pointer */
  94. };
  95. #define NULLPERMLINK  ((struct permlink *) 0)
  96.  
  97. static struct permlink *permlinks;
  98.  
  99. static struct convection * near alloc_connection __ARGS((int fd));
  100. static char * near getarg __ARGS((char *line, int all));
  101. static char * near timestring __ARGS((int32 gmt));
  102. static void near free_connection __ARGS((struct convection *cp));
  103. static char * formatline __ARGS((char  *prefix,char *text));
  104. static void near clear_locks __ARGS((void));
  105. static void send_msg_to_user __ARGS((char *fromname,char *toname,char *text));
  106. static void send_msg_to_channel __ARGS((char *fromname,int channel,char *text));
  107. static void near update_permlinks __ARGS((char *name,struct convection *cp));
  108. static void send_user_change_msg __ARGS((char *name,char *host,int oldchannel,int newchannel));
  109. static void bye_command __ARGS((struct convection *cp));
  110. static void send_invite_msg __ARGS((char *fromname,char *toname,int channel));
  111. static void near free_closed_connections __ARGS((void));
  112.  
  113. /* Stop convers server */
  114. int
  115. conv0(argc,argv,p)
  116. int argc;
  117. char *argv[];
  118. void *p;
  119. {
  120. #ifdef LINK
  121. #ifdef LZW
  122.     if(Sxconv == -1) {
  123.         killproc(child);
  124.         child = NULLPROC;
  125.     }
  126. #else
  127.     killproc(child);
  128.     child = NULLPROC;
  129. #endif
  130. #endif
  131.     close_s(Sconv);
  132.     Sconv = -1;
  133.     return 0;
  134. }
  135.  
  136. #ifdef LZW
  137. /* Stop xconvers server */
  138. int
  139. xconv0(argc,argv,p)
  140. int argc;
  141. char *argv[];
  142. void *p;
  143. {
  144. #ifdef LINK
  145.     if(Sconv == -1) {
  146.         killproc(child);
  147.         child = NULLPROC;
  148.     }
  149. #endif
  150.     close_s(Sxconv);
  151.     Sxconv = -1;
  152.     return 0;
  153. }
  154. #endif
  155.  
  156. /* Start up convers server */
  157. int
  158. conv1(argc,argv,p)
  159. int argc;
  160. char *argv[];
  161. void *p;
  162. {
  163.     struct sockaddr_in lsocket;
  164.     int s;
  165.  
  166.     if(Sconv != -1)
  167.         return 0;
  168.  
  169.     psignal(Curproc,0);         /* Don't keep the parser waiting */
  170.     chname(Curproc,"Convers listener");
  171.  
  172.     lsocket.sin_family = AF_INET;
  173.     lsocket.sin_addr.s_addr = INADDR_ANY;
  174.     lsocket.sin_port = (argc < 2) ? IPPORT_CONVERS : atoi(argv[1]);
  175.  
  176.     Sconv = socket(AF_INET,SOCK_STREAM,0);
  177.     bind(Sconv,(char *)&lsocket,sizeof(lsocket));
  178.     listen(Sconv,1);
  179. #ifdef LINK
  180.     if(child == NULLPROC)
  181.         child = newproc("cperm",1024,connect_permlinks,0,0,NULL,0);
  182. #else
  183.     myhostname = strxdup(Hostname);
  184. #endif
  185.     for(;;){
  186.         if((s = accept(Sconv,NULLCHAR,(int *)NULL)) == -1)
  187.             break;            /* Service is shutting down */
  188.  
  189.         if(availmem() < Memthresh){
  190.             shutdown(s,1);
  191.         } else {
  192.             /* Spawn a server */
  193.             newproc("conversd",2048,conv_incom,s,0,NULL,0);
  194.         }
  195.     }
  196.     return 0;
  197. }
  198.  
  199. #ifdef LZW
  200. /* Start up xconvers server */
  201. int
  202. xconv1(argc,argv,p)
  203. int argc;
  204. char *argv[];
  205. void *p;
  206. {
  207.     struct sockaddr_in lsocket;
  208.     int s;
  209.  
  210.     if(Sxconv != -1)
  211.         return 0;
  212.  
  213.     psignal(Curproc,0);         /* Don't keep the parser waiting */
  214.     chname(Curproc,"XConv listener");
  215.  
  216.     lsocket.sin_family = AF_INET;
  217.     lsocket.sin_addr.s_addr = INADDR_ANY;
  218.     lsocket.sin_port = (argc < 2) ? IPPORT_XCONVERS : atoi(argv[1]);
  219.  
  220.     Sxconv = socket(AF_INET,SOCK_STREAM,0);
  221.     bind(Sxconv,(char *)&lsocket,sizeof(lsocket));
  222.     listen(Sxconv,1);
  223. #ifdef LINK
  224.     if(child == NULLPROC)
  225.         child = newproc("cperm",1024,connect_permlinks,0,0,NULL,0);
  226. #else
  227.     myhostname = strxdup(Hostname);
  228. #endif
  229.     for(;;){
  230.         if((s = accept(Sxconv,NULLCHAR,(int *)NULL)) == -1)
  231.             break;            /* Service is shutting down */
  232.  
  233.         if(availmem() < Memthresh){
  234.             shutdown(s,1);
  235.         } else {
  236.             /* Spawn a server */
  237.             newproc("xconversd",2048,conv_incom,s,(void *)1,NULL,0);
  238.         }
  239.     }
  240.     return 0;
  241. }
  242. #endif
  243.  
  244. static char * near
  245. getarg(line, all)
  246. char  *line;
  247. int  all;
  248. {
  249.   char  *arg;
  250.   int  c;
  251.   static char  *p;
  252.  
  253.   if (line) p = line;
  254.   while (isspace(uchar(*p))) p++;
  255.   if (all) return p;
  256.   arg = p;
  257.   while (*p && !isspace(uchar(*p))) {
  258.     c = tolower(uchar(*p));
  259.     *p++ = c;
  260.   }
  261.   if (*p) *p++ = '\0';
  262.   return arg;
  263. }
  264.  
  265. static void near
  266. free_connection(cp)
  267. struct convection *cp;
  268. {
  269.   struct permlink *p;
  270.  
  271.   for (p = permlinks; p; p = p->next)
  272.     if (p->convection == cp) p->convection = NULLCONNECTION;
  273.   if (cp->fmask) close_s(cp->fd);
  274.   xfree(cp->ibuf);
  275.   xfree((char *)cp);
  276. }
  277.  
  278. static void near
  279. free_closed_connections()
  280. {
  281.   struct convection *cp, *p;
  282.  
  283.   for (p = NULLCONNECTION, cp = convections; cp; )
  284.     if (cp->type == CT_CLOSED ||
  285.      cp->type == CT_UNKNOWN && cp->time + 300 < currtime) {
  286.       if (p) {
  287.         p->next = cp->next;
  288.         free_connection(cp);
  289.         cp = p->next;
  290.       } else {
  291.         convections = cp->next;
  292.         free_connection(cp);
  293.         cp = convections;
  294.       }
  295.     } else {
  296.       p = cp;
  297.       cp = cp->next;
  298.     }
  299. }
  300.  
  301. static void near
  302. update_permlinks(name, cp)
  303. char  *name;
  304. struct convection *cp;
  305. {
  306.   struct permlink *p;
  307.  
  308.   for (p = permlinks; p; p = p->next)
  309.     if (!strcmp(p->name, name)) {
  310.       p->convection = cp;
  311.       p->statetime = currtime;
  312.       p->tries = 0;
  313.       p->waittime = 60;
  314.       p->retrytime = currtime + p->waittime;
  315.     }
  316. }
  317.  
  318. static struct convection * near
  319. alloc_connection(fd)
  320. int  fd;
  321. {
  322.   struct convection *cp =
  323.     (struct convection *)mxallocw(sizeof(struct convection));
  324.  
  325.   cp->fd = cp->fmask = fd;
  326.   cp->time = currtime;
  327.   cp->next = convections;
  328.   cp->ibuf = mxallocw(CBUFLEN);
  329.   convections = cp;
  330.   return cp;
  331. }
  332.  
  333. #ifdef LINK
  334. void
  335. connect_permlinks(a,b,c)
  336. int a;
  337. void *b;
  338. void *c;
  339. {
  340.   int s, x, len = SOCKSIZE;
  341.   struct permlink *p;
  342.   struct sockaddr_in cport;
  343.   FILE *fp;
  344.   char *host_name, *link_info, *command, line[LINELEN];
  345.  
  346.   if ((fp = fopen(Convers,"r")) == NULLFILE) {
  347.     if(myhostname == NULLCHAR) {
  348.       myhostname = strxdup(Hostname);
  349.     }
  350.   } else {
  351.     while (fgets(line, LINELEN, fp)) {
  352.       rip(line);
  353.       if(*line == '#' || *line == '\0') continue;
  354.       host_name = getarg(line,0);
  355.       link_info = getarg(0,0);
  356.       command = getarg(0,0);
  357.  
  358.       if(host_name == NULLCHAR) continue;
  359.  
  360.       if (myhostname == NULLCHAR) {
  361.         myhostname = strxdup(host_name);
  362.         continue;
  363.       }
  364.       if (link_info != NULLCHAR) {
  365.         p = (struct permlink *)mxallocw(sizeof(struct permlink));
  366.         sprintf(p->name,"%.79s",host_name);
  367.         sprintf(p->link_info,"%.79s",link_info);
  368.         if(command != NULLCHAR)
  369.           sprintf(p->command,"%.79s",command);
  370.         p->next = permlinks;
  371.         permlinks = p;
  372.         update_permlinks(host_name, NULLCONNECTION);
  373.       }
  374.     }
  375.     fclose(fp);
  376.   }
  377.  
  378.   for(;;) {
  379.     pause(1000L);
  380.     for (p = permlinks; p; p = p->next) {
  381.       if (p->convection || p->retrytime > currtime) continue;
  382.       p->tries++;
  383.       p->waittime <<= 1;
  384.       if (p->waittime > MAX_WAITTIME) p->waittime = MAX_WAITTIME;
  385.       p->retrytime = p->waittime + currtime;
  386.       x = 0;
  387.       switch(tolower(*p->link_info)) {
  388.       case 'x':                            /* compressed telnet connection */
  389.           x = 1;
  390.       case 't':                            /* telnet connection */
  391.           cport.sin_family = AF_INET;
  392.           cport.sin_port = x ? IPPORT_XCONVERS : IPPORT_CONVERS;
  393.           if((cport.sin_addr.s_addr = resolve(p->name)) != 0) {
  394.               if((s = socket(AF_INET,SOCK_STREAM,0)) != -1) {
  395.                   if(connect(s,(char *)&cport,len) != -1) {
  396.                       p->fd = s;
  397.                       newproc("permlink",2048,conv_incom,s,(void *)x,NULL,0);
  398.                   } else {
  399.                       close_s(s);
  400.                   }
  401.               }
  402.           }
  403.           break;
  404.  
  405. /*      case 'a':                            /* ax25 connection   */
  406. /*      case 'n':                            /* netrom connection */
  407. /*      default:                                                 */
  408. /*          continue;                                             */
  409.       }
  410.     }
  411.   }
  412. }
  413. #endif
  414.  
  415.  
  416. static void near
  417. clear_locks()
  418. {
  419.   struct convection *p;
  420.  
  421.   for (p = convections; p; p = p->next) p->locked = 0;
  422. }
  423.  
  424. static void
  425. send_user_change_msg(name, host, oldchannel, newchannel)
  426. char  *name, *host;
  427. int  oldchannel, newchannel;
  428. {
  429.   struct convection *p;
  430.  
  431.   for (p = convections; p; p = p->next) {
  432.     if (p->type == CT_USER && !p->via && !p->locked) {
  433.       if (p->channel == oldchannel) {
  434.         if (newchannel >= 0)
  435.           p->xmitted += usprintf(p->fd, "*** %s switched to channel %d.\n", name, newchannel);
  436.         else
  437.           p->xmitted += usprintf(p->fd, "*** %s signed off.\n", name);
  438.         p->locked = 1;
  439.       }
  440.       if (p->channel == newchannel) {
  441.         p->xmitted += usprintf(p->fd, "*** %s signed on.\7\n", name);
  442.         p->locked = 1;
  443.       }
  444.     }
  445.     if (p->type == CT_HOST && !p->locked) {
  446.       p->xmitted += usprintf(p->fd,
  447.         "/\377\200USER %s %s 0 %d %d\n",
  448.         name, host, oldchannel, newchannel);
  449.       p->locked = 1;
  450.     }
  451.   }
  452.   return;
  453. }
  454.  
  455. static char *
  456. formatline(prefix, text)
  457. char  *prefix, *text;
  458. {
  459.  
  460. #define PREFIXLEN 10
  461. #define CONVLINELEN   79
  462.  
  463.   char  *f, *t, *x;
  464.   int  l, lw;
  465.   static char buf[2048];
  466.  
  467.   for (f = prefix, t = buf; *f; *t++ = *f++) ;
  468.   l = (int)(t - buf);
  469.   f = text;
  470.  
  471.   for (; ; ) {
  472.     while (isspace(uchar(*f))) f++;
  473.     if (!*f) {
  474.       *t++ = '\n';
  475.       *t = '\0';
  476.       return buf;
  477.     }
  478.     for (x = f; *x && !isspace(uchar(*x)); x++) ;
  479.     lw = (int)(x - f);
  480.     if (l > PREFIXLEN && l + 1 + lw > CONVLINELEN) {
  481.       *t++ = '\n';
  482.       l = 0;
  483.     }
  484.     do {
  485.       *t++ = ' ';
  486.       l++;
  487.     } while (l < PREFIXLEN);
  488.     while (lw--) {
  489.       *t++ = *f++;
  490.       l++;
  491.     }
  492.   }
  493. }
  494.  
  495. static void
  496. send_msg_to_user(fromname, toname, text)
  497. char  *fromname, *toname, *text;
  498. {
  499.   struct convection *p;
  500.   char *buffer = mxallocw(CBUFLEN);
  501.  
  502.   for (p = convections; p; p = p->next) {
  503.     if (p->type == CT_USER && !strcmp(p->name, toname))
  504.       if (p->via) {
  505.         if (!p->via->locked) {
  506.           p->via->xmitted += usprintf(p->via->fd,
  507.             "/\377\200UMSG %s %s %s\n", fromname, toname, text);
  508.           p->via->locked = 1;
  509.         }
  510.       } else {
  511.         if (!p->locked) {
  512.           if (strcmp(fromname, "conversd")) {
  513.             sprintf(buffer, "<*%s*>:", fromname);
  514.             p->xmitted += usprintf(p->fd,"%s",formatline(buffer, text));
  515.         } else {
  516.             p->xmitted += usprintf(p->fd,"%s\n",text);
  517.         }
  518.       p->locked = 1;
  519.       }
  520.     }
  521.   }
  522.   xfree(buffer);
  523.   return;
  524. }
  525.  
  526. static void
  527. send_msg_to_channel(fromname, channel, text)
  528. char  *fromname;
  529. int  channel;
  530. char  *text;
  531. {
  532.   struct convection *p;
  533.   char *buffer = mxallocw(CBUFLEN);
  534.  
  535.   for (p = convections; p; p = p->next) {
  536.     if (p->type == CT_USER && p->channel == channel)
  537.       if (p->via) {
  538.         if (!p->via->locked) {
  539.           p->via->xmitted += usprintf(p->via->fd,
  540.             "/\377\200CMSG %s %d %s\n", fromname, channel, text);
  541.           p->via->locked = 1;
  542.         }
  543.       } else {
  544.         if (!p->locked) {
  545.           sprintf(buffer, "<%s>:", fromname);
  546.           p->xmitted += usprintf(p->fd,"%s",formatline(&buffer[0],text));
  547.           p->locked = 1;
  548.       }
  549.     }
  550.   }
  551.   xfree(buffer);
  552.   return;
  553. }
  554.  
  555. static char * near
  556. timestring(gmt)
  557. int32 gmt;
  558. {
  559.   static char buffer[10];
  560.   struct tm *tm = localtime(&gmt);
  561.  
  562.   if (gmt + 24 * 60 * 60 > currtime)
  563.     sprintf(buffer, " %2d:%02d", tm->tm_hour, tm->tm_min);
  564.   else
  565.     sprintf(buffer, "%-3.3s %2d", Months[tm->tm_mon - 1], tm->tm_mday);
  566.  
  567.   return buffer;
  568. }
  569.  
  570. static void
  571. send_invite_msg(fromname, toname, channel)
  572. char  *fromname, *toname;
  573. int  channel;
  574. {
  575.   char invitetext[] = "\n\007\007*** Message from %s at%s ...\nPlease join convers channel %d.\n\007\007\n";
  576.   char responsetext[] = "*** Invitation sent to %s @ %s";
  577.   char cnvd[] = "conversd";
  578.  
  579.   char *buffer = mxallocw(CBUFLEN);
  580.  
  581.   struct convection *p;
  582. #ifdef MAILBOX
  583.   int i;
  584.   struct mbx *m;
  585. #endif
  586.  
  587.   for (p = convections; p; p = p->next) {
  588. #ifdef MAILBOX
  589.     for (i = 0; i < NUMMBX; i++){
  590.       if((m = Mbox[i]) != NULLMBX){
  591.         if(m->state == MBX_CMD && !strcmp(m->name,toname)) {
  592.           p->xmitted += usprintf(m->user, invitetext, fromname, timestring(currtime), channel);
  593.           usflush(m->user);
  594.           clear_locks();
  595.           sprintf(buffer, responsetext, toname, "LocBBS@");
  596.           strcat(buffer,Hostname);
  597.           send_msg_to_user(cnvd, fromname, buffer);
  598.           xfree(buffer);
  599.           return;
  600.         }
  601.       }
  602.     }
  603. #endif
  604.     if (p->type == CT_USER && !strcmp(p->name, toname)) {
  605.       if (p->channel == channel) {
  606.         clear_locks();
  607.         sprintf(buffer, "*** User %s is already on this channel.", toname);
  608.         send_msg_to_user(cnvd, fromname, buffer);
  609.         xfree(buffer);
  610.         return;
  611.       }
  612.       if (!p->via && !p->locked) {
  613.         p->xmitted += usprintf(p->fd, invitetext, fromname, timestring(currtime), channel);
  614.         clear_locks();
  615.         sprintf(buffer, responsetext, toname, myhostname);
  616.         send_msg_to_user(cnvd, fromname, buffer);
  617.         xfree(buffer);
  618.         return;
  619.       }
  620.       if (p->via && !p->via->locked) {
  621.         p->via->xmitted += usprintf(p->via->fd,
  622.           "/\377\200INVI %s %s %d\n", fromname, toname, channel);
  623.         xfree(buffer);
  624.         return;
  625.       }
  626.     }
  627.   }
  628.   for (p = convections; p; p = p->next) {
  629.     if (p->type == CT_HOST && !p->locked) {
  630.       p->xmitted += usprintf(p->fd,
  631.         "/\377\200INVI %s %s %d\n", fromname, toname, channel);
  632.     }
  633.   }
  634.   xfree(buffer);
  635.   return;
  636. }
  637.  
  638. static void
  639. bye_command(cp)
  640. struct convection *cp;
  641. {
  642.   struct convection *p;
  643.  
  644.   switch (cp->type) {
  645.   case CT_UNKNOWN:
  646.     cp->type = CT_CLOSED;
  647.     break;
  648.   case CT_USER:
  649.     cp->type = CT_CLOSED;
  650.     clear_locks();
  651.     send_user_change_msg(cp->name, cp->host, cp->channel, -1);
  652.     break;
  653.   case CT_HOST:
  654.     cp->type = CT_CLOSED;
  655.     update_permlinks(cp->name, NULLCONNECTION);
  656.     for (p = convections; p; p = p->next)
  657.       if (p->via == cp) {
  658.         p->type = CT_CLOSED;
  659.         clear_locks();
  660.         send_user_change_msg(p->name, p->host, p->channel, -1);
  661.       }
  662.     break;
  663.   case CT_CLOSED:
  664.     break;
  665.   }
  666. }
  667.  
  668. static void
  669. channel_command(cp)
  670. struct convection *cp;
  671. {
  672.   int newchannel;
  673.  
  674.   char *s = getarg(0,0);
  675.  
  676.   if (!*s) {
  677.     cp->xmitted += usprintf(cp->fd,"*** You are on channel %d.\n",cp->channel);
  678.     return;
  679.   }
  680.   newchannel = atoi(s);
  681.   if (newchannel < 0 || newchannel > MAXCHANNEL) {
  682.     cp->xmitted += usprintf(cp->fd,cnumber,MAXCHANNEL);
  683.     return;
  684.   }
  685.   if (newchannel == cp->channel) {
  686.     cp->xmitted += usprintf(cp->fd,
  687.       "*** Already on channel %d.\n", cp->channel);
  688.     return;
  689.   }
  690.   send_user_change_msg(cp->name, cp->host, cp->channel, newchannel);
  691.   cp->channel = newchannel;
  692.   cp->xmitted += usprintf(cp->fd, "*** Now on channel %d.\n", cp->channel);
  693.   return;
  694. }
  695.  
  696. static void
  697. help_command(cp)
  698. struct convection *cp;
  699. {
  700.   cp->xmitted += usputs(cp->fd, "Commands may be abbreviated. Commands are:\n");
  701.   cp->xmitted += usputs(cp->fd, "/?                   Print help information\n");
  702.   cp->xmitted += usputs(cp->fd, "/BYE                 Terminate the convers session\n");
  703.   cp->xmitted += usputs(cp->fd, "/CHANNEL n           Switch to channel n\n");
  704.   cp->xmitted += usputs(cp->fd, "/EXIT                Terminate the convers session\n");
  705.   cp->xmitted += usputs(cp->fd, "/HELP                Print help information\n");
  706.   cp->xmitted += usputs(cp->fd, "/INVITE user         Invite user to join your channel\n");
  707.   cp->xmitted += usputs(cp->fd, "/LINKS [LONG]        List all connections to other hosts\n");
  708.   cp->xmitted += usputs(cp->fd, "/MSG user text...    Send a private message to user\n");
  709.   cp->xmitted += usputs(cp->fd, "/QUIT                Terminate the convers session\n");
  710.   cp->xmitted += usputs(cp->fd, "/WHO [QUICK] [LONG]  List all users and their channel numbers\n");
  711.   cp->xmitted += usputs(cp->fd, "/WRITE user text...  Send a private message to user\n***\n");
  712.   return;
  713. }
  714.  
  715. static void
  716. invite_command(cp)
  717. struct convection *cp;
  718. {
  719.   char *toname = getarg(0,0);
  720.  
  721.   if (*toname) send_invite_msg(cp->name, toname, cp->channel);
  722. }
  723.  
  724. static void
  725. links_command(cp)
  726. struct convection *cp;
  727. {
  728.   char  tmp[20];
  729.   struct convection *pc;
  730.   struct permlink *pp;
  731.  
  732.   int full = *(getarg(0,0));
  733.  
  734.   cp->xmitted += usprintf(cp->fd,"Host     State         Since%s\n",
  735.     full ? " NextTry Tries Queue Receivd Xmitted" : "");
  736.   for (pc = convections; pc; pc = pc->next)
  737.     if (pc->type == CT_HOST) {
  738.       cp->xmitted += usprintf(cp->fd,
  739.         full ?
  740.         "%-8.8s %-12s %s%15d %7d %7d\n" :
  741.         "%-8.8s %-12s %s\n",
  742.           pc->name,
  743.           "Connected",
  744.           timestring(pc->time),
  745.           0,            /* always 0, cuz NOS handles the tx-queue */
  746.           pc->received,
  747.           pc->xmitted);
  748.     }
  749.   for (pp = permlinks; pp; pp = pp->next)
  750.     if (!pp->convection || pp->convection->type != CT_HOST) {
  751.       strcpy(tmp, timestring(pp->retrytime)),
  752.       cp->xmitted += usprintf(cp->fd,
  753.         full ?
  754.         "%-8.8s %-12s %s  %s %5d\n" :
  755.         "%-8.8s %-12s %s\n",
  756.           pp->name,
  757.           pp->convection ? "Connecting" : "Disconnected",
  758.           timestring(pp->statetime),
  759.           tmp,
  760.           pp->tries);
  761.     }
  762.   cp->xmitted += usputs(cp->fd,"***\n");
  763.   return;
  764. }
  765.  
  766. static void
  767. msg_command(cp)
  768. struct convection *cp;
  769. {
  770.  
  771.   struct convection *p;
  772.  
  773.   char *toname = getarg(0,0);
  774.   char *text = getarg(0,1);
  775.  
  776.   if (!*text) return;
  777.   for (p = convections; p; p = p->next)
  778.     if (p->type == CT_USER && !strcmp(p->name, toname))
  779.       break;
  780.   if (!p)
  781.     cp->xmitted += usprintf(cp->fd, "*** No such user: %s.\n", toname);
  782.   else
  783.     send_msg_to_user(cp->name, toname, text);
  784.   return;
  785. }
  786.  
  787. static void
  788. name_command(cp)
  789. struct convection *cp;
  790. {
  791.   int newchannel;
  792.  
  793.   char *s = getarg(0,0);
  794.   if(!*s)
  795.     return;
  796.   sprintf(cp->name,"%.79s",s);
  797.   strlwr(cp->name);
  798.   cp->type = CT_USER;
  799.   sprintf(cp->host,"%.79s",myhostname);
  800.   cp->xmitted += usprintf(cp->fd,
  801.     "conversd @ %s $WNOS_Rev: B(2.17) $ Type /HELP for help.\n", myhostname);
  802.  
  803.   newchannel = atoi(getarg(0,0));
  804.  
  805.   if (newchannel < 0 || newchannel > MAXCHANNEL) {
  806.     cp->xmitted += usprintf(cp->fd,cnumber,MAXCHANNEL);
  807.   } else
  808.     cp->channel = newchannel;
  809.   send_user_change_msg(cp->name, cp->host, -1, cp->channel);
  810.   return;
  811. }
  812.  
  813. static void
  814. who_command(cp)
  815. struct convection *cp;
  816. {
  817.  
  818.   int channel, full = 0, quick = 0;
  819.   struct convection *p;
  820. #ifdef MAILBOX
  821.   int i;
  822.   struct mbx *m;
  823. #endif
  824.  
  825.   char *buffer = mxallocw(CBUFLEN);
  826.  
  827.   switch(*(getarg(0,0))) {
  828.   case 'l':
  829.     full = 1;
  830.     break;
  831.   case 'q':
  832.     quick = 1;
  833.     break;
  834.   }
  835.  
  836.   if (quick) {
  837.     cp->xmitted += usprintf(cp->fd, "Channel Users\n");
  838.     clear_locks();
  839.     do {
  840.       channel = -1;
  841.       for (p = convections; p; p = p->next) {
  842.         if (p->type == CT_USER && !p->locked && (channel < 0 || channel == p->channel)) {
  843.           if (channel < 0) {
  844.             channel = p->channel;
  845.             sprintf(buffer, "%7d", channel);
  846.           }
  847.           strcat(buffer, " ");
  848.           strcat(buffer, p->name);
  849.           p->locked = 1;
  850.         }
  851.       }
  852.       if (channel >= 0) {
  853.         cp->xmitted += usprintf(cp->fd, "%s\n",buffer);
  854.       }
  855.     } while (channel >= 0);
  856.   } else {
  857.     cp->xmitted += usprintf(cp->fd,
  858.       "User     Host     Via      Channel   Time%s\n",
  859.       full ? " HQueue Receivd Xmitted" : "");
  860.     for (p = convections; p; p = p->next) {
  861.       if (p->type == CT_USER) {
  862.         cp->xmitted += usprintf(cp->fd,"%-8.8s %-8.8s %-8.8s %7d %s",
  863.           p->name,
  864.           p->host,
  865.           p->via ? p->via->name : "",
  866.           p->channel,
  867.           timestring(p->time));
  868.         if(full)
  869.           cp->xmitted += usprintf(cp->fd,"%7d %7d %7d",
  870.             0,            /* always 0 cuz NOS handles the tx-queue */
  871.             p->received,
  872.             p->xmitted);
  873.         cp->xmitted += usputs(cp->fd,"\n");
  874.       }
  875.     }
  876.   }
  877. #ifdef MAILBOX
  878.   for (i = 0; i < NUMMBX; i++) {
  879.     if((m = Mbox[i]) != NULLMBX) {
  880.       if(m->state == MBX_CMD) {
  881.         if(quick)
  882.           cp->xmitted += usprintf(cp->fd," LocBBS %s\n",m->name);
  883.         else
  884.           cp->xmitted += usprintf(cp->fd,"%-8s LocBBS@%s\n",m->name,Hostname);
  885.       }
  886.     }
  887.   }
  888. #endif
  889.   cp->xmitted += usputs(cp->fd, "***\n");
  890.   xfree(buffer);
  891.   return;
  892. }
  893.  
  894. static void
  895. h_cmsg_command(cp)
  896. struct convection *cp;
  897. {
  898.  
  899.   char *name = getarg(0, 0);
  900.   int channel = atoi(getarg(0, 0));
  901.   char *text = getarg(0, 1);
  902.  
  903.   if (*text) send_msg_to_channel(name, channel, text);
  904. }
  905.  
  906. static void
  907. h_host_command(cp)
  908. struct convection *cp;
  909. {
  910.   struct convection *p;
  911.   struct permlink *pp;
  912.  
  913.   char *name = getarg(0,0);
  914.  
  915.   if (!*name) return;
  916.   for (p = convections; p; p = p->next)
  917.     if (!strcmp(p->name, name)) bye_command(p);
  918.   for (pp = permlinks; pp; pp = pp->next)
  919.     if (!strcmp(pp->name, name) && pp->convection && pp->convection != cp)
  920.       bye_command((strcmp(myhostname, name) < 0) ? pp->convection : cp);
  921.   if (cp->type != CT_UNKNOWN) return;
  922.   cp->type = CT_HOST;
  923.   strcpy(cp->name,name);        /* already allocated */
  924.   update_permlinks(name, cp);
  925.   cp->xmitted += usprintf(cp->fd, "/\377\200HOST %s\n", myhostname);
  926.   for (p = convections; p; p = p->next)
  927.     if (p->type == CT_USER) {
  928.       cp->xmitted += usprintf(cp->fd,
  929.         "/\377\200USER %s %s 0 -1 %d\n", p->name, p->host, p->channel);
  930.     }
  931.   return;
  932. }
  933.  
  934. static void
  935. h_invi_command(cp)
  936. struct convection *cp;
  937. {
  938.  
  939.   char *fromname = getarg(0,0);
  940.   char *toname = getarg(0,0);
  941.   int channel = atoi(getarg(0,0));
  942.  
  943.   send_invite_msg(fromname, toname, channel);
  944. }
  945.  
  946. static void
  947. h_umsg_command(cp)
  948. struct convection *cp;
  949. {
  950.  
  951.   char *fromname = getarg(0, 0);
  952.   char *toname = getarg(0, 0);
  953.   char *text = getarg(0, 1);
  954.  
  955.   if (*text) send_msg_to_user(fromname, toname, text);
  956. }
  957.  
  958. static void
  959. h_user_command(cp)
  960. struct convection *cp;
  961. {
  962.   int oldchannel, newchannel;
  963.   struct convection *p;
  964.  
  965.   char *name = getarg(0, 0);
  966.   char *host = getarg(0, 0);
  967.   getarg(0, 0);            /*** ignore this argument, protocol has changed ***/
  968.   oldchannel = atoi(getarg(0, 0));
  969.   newchannel = atoi(getarg(0, 0));
  970.  
  971.   for (p = convections; p; p = p->next)
  972.     if (p->type == CT_USER   &&
  973.     p->channel == oldchannel &&
  974.     p->via == cp             &&
  975.     !strcmp(p->name, name)   &&
  976.     !strcmp(p->host, host))  break;
  977.   if (!p) {
  978.     p = (struct convection *)mxallocw(sizeof(struct convection ));
  979.     p->type = CT_USER;
  980.     sprintf(p->name,"%.79s",name);
  981.     sprintf(p->host,"%.79s",host);
  982.     p->via = cp;
  983.     p->channel = oldchannel;
  984.     p->time = currtime;
  985.     p->next = convections;
  986.     convections = p;
  987.   }
  988.   if ((p->channel = newchannel) < 0) p->type = CT_CLOSED;
  989.   send_user_change_msg(name, host, oldchannel, newchannel);
  990. }
  991.  
  992. /* Incoming convers session */
  993. void
  994. conv_incom(s,t,p)
  995. int s;
  996. void *t;
  997. void *p;
  998. {
  999.   int arglen, size;
  1000.   struct convection *cp;
  1001.   struct permlink *pl;
  1002.   char *arg, *ccp, *cccp;
  1003.  
  1004. #ifdef MAILBOX
  1005.   int len;
  1006.   char fsocket[MAXSOCKSIZE];
  1007. #endif
  1008.  
  1009.   struct cmdtable {
  1010.     char  *name;
  1011.     void (*fnc)();
  1012.     int  states;
  1013.   } cmdtable[] = {
  1014.     "?",          help_command,       CM_USER,
  1015.     "bye",        bye_command,        CM_USER,
  1016.     "channel",    channel_command,    CM_USER,
  1017.     "exit",       bye_command,        CM_USER,
  1018.     "help",       help_command,       CM_USER,
  1019.     "invite",     invite_command,     CM_USER,
  1020.     "links",      links_command,      CM_USER,
  1021.     "msg",        msg_command,        CM_USER,
  1022.     "name",       name_command,       CM_UNKNOWN,
  1023.     "quit",       bye_command,        CM_USER,
  1024.     "who",        who_command,        CM_USER,
  1025.     "write",      msg_command,        CM_USER,
  1026.  
  1027.     "\377\200cmsg", h_cmsg_command,   CM_HOST,
  1028.     "\377\200host", h_host_command,   CM_UNKNOWN,
  1029.     "\377\200invi", h_invi_command,   CM_HOST,
  1030.     "\377\200umsg", h_umsg_command,   CM_HOST,
  1031.     "\377\200user", h_user_command,   CM_HOST,
  1032.  
  1033.     0, 0, 0,
  1034.   };
  1035.   struct cmdtable *cmdp;
  1036.  
  1037.   sockowner(s,Curproc);    /* We own it now */
  1038.   sockmode(s,SOCK_BINARY);
  1039.   time(&currtime);
  1040.   cp = alloc_connection(s);
  1041.  
  1042. #ifdef LZW
  1043.   if((int)t == 1)
  1044.     lzwinit(s,Lzwbits,Lzwmode);
  1045. #endif
  1046.  
  1047.   for(pl = permlinks; pl; pl = pl->next)
  1048.     if(pl->fd == s) {
  1049.       pl->convection = cp;
  1050.       if (pl->command != NULLCHAR) usprintf(s, "%s\n", pl->command);
  1051.       cp->xmitted += usprintf(s, "/\377\200HOST %s\n", myhostname);
  1052.     }
  1053.  
  1054.   if(pl == NULLPERMLINK) {
  1055. #ifdef MAILBOX
  1056.     getpeername(s,fsocket,&len);
  1057.     ccp = strxdup(psocket(fsocket));
  1058.     if((cccp = strchr(ccp,':')) != NULLCHAR)
  1059.       *cccp = '\0';
  1060.     if(strcmp(ccp,inet_ntoa(Ip_addr)) != 0)
  1061.       usprintf(cp->fd,"\npse login with '/n <call>'\n\n");
  1062.     xfree(ccp);
  1063. #else
  1064.     usprintf(cp->fd,"\npse login with '/n <call>'\n\n");
  1065. #endif
  1066.   }
  1067.  
  1068.   for (; ; ) {
  1069. loop:
  1070.     if(cp->type == CT_CLOSED)
  1071.       break;
  1072.     if((size = recvline(cp->fd,cp->ibuf,CBUFLEN)) <= 0) {
  1073.       break;
  1074.     }
  1075.     cp->received += size;
  1076.     clear_locks();
  1077.     cp->locked = 1;
  1078.     if((ccp = strpbrk(cp->ibuf,"\r\n")) != NULLCHAR)
  1079.         *ccp = '\0';
  1080.     if (*cp->ibuf == '/') {
  1081.         arglen = strlen(arg = getarg(cp->ibuf + 1, 0));
  1082.         for (cmdp = cmdtable; cmdp->name; cmdp++)
  1083.             if (!strnicmp(cmdp->name, arg, arglen)) {
  1084.                 if (cmdp->states & (1 << cp->type))
  1085.                     (*cmdp->fnc)(cp);
  1086.                 goto loop;
  1087.                 }
  1088.         if (cp->type == CT_USER) {
  1089.             cp->xmitted += usprintf(cp->fd,
  1090.                 "*** Unknown command '/%s'. Type /HELP for help.\n", arg);
  1091.             }
  1092.         goto loop;
  1093.     }
  1094.     if(isprint(*cp->ibuf) != 0 && cp->type == CT_USER)
  1095.       send_msg_to_channel(cp->name, cp->channel, cp->ibuf);
  1096.   }
  1097.   bye_command(cp);
  1098.   free_closed_connections();
  1099.   return;
  1100. }
  1101.  
  1102.  
  1103. #endif /* CONVERS */
  1104.